package com.appengine.tnovoselec;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;

import com.google.appengine.api.blobstore.BlobKey;
import com.google.appengine.api.files.AppEngineFile;
import com.google.appengine.api.files.FileReadChannel;
import com.google.appengine.api.files.FileService;
import com.google.appengine.api.files.FileServiceFactory;

@SuppressWarnings("serial")
public class GoogleWeatherServlet extends HttpServlet {

	public static Map<String, Source> CACHE = new HashMap<String, Source>(100);
	public static Map<String, String> OUTPUT_PROPERTIES = new HashMap<String, String>(5, 1.1F);
	FileService fileService = FileServiceFactory.getFileService();
	public static BlobKey meteoKey = null;
	public static BlobKey gasPrices = null;
	public static BlobKey exchangeRates = null;
	public static String blobMeteoKey = "blobMeteoKey";
	public static String blobGasPricesKey = "gasPricesKey";
	public static String blobExchangeRatesKey = "exchangeRatesKey";
	public static String cleanBlobstore = "cleanBlobstore";
	
	static {
		GoogleWeatherServlet.OUTPUT_PROPERTIES.put(OutputKeys.INDENT, "yes");
		GoogleWeatherServlet.OUTPUT_PROPERTIES.put(OutputKeys.ENCODING, Config.encoding);
		GoogleWeatherServlet.OUTPUT_PROPERTIES.put(OutputKeys.VERSION, "1.0");
		GoogleWeatherServlet.OUTPUT_PROPERTIES.put(OutputKeys.MEDIA_TYPE, XMLUtil.XML_CONTENT_TYPE);
		GoogleWeatherServlet.OUTPUT_PROPERTIES.put("{http://xml.apache.org/xslt}indent-amount", "4");
	}

	public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {

		String key = req.getParameter(Config.key);
		String city = req.getParameter(Config.city);

		if (key != null && key.equals(Config.refreshKey)) {
			RefreshCache rc = new RefreshCache(fileService);
			rc.doRefresh();
		} else if (key != null && key.equals(Config.gasPricesKey)) {
			AppEngineFile f = fileService.getBlobFile(gasPrices);
			FileReadChannel ch = null;
			try {
				ch = fileService.openReadChannel(f, false);
			} catch (Exception e) {
				e.printStackTrace();
			}

			ByteArrayOutputStream out = new ByteArrayOutputStream();
			long checkSum = 0L;
			try {
				byte[] barray = new byte[1024];
				ByteBuffer bb = ByteBuffer.wrap(barray);
				int nRead;
				while ((nRead = ch.read(bb)) != -1) {
					for (int i = 0; i < nRead; i++) {
						checkSum += barray[i];
						try {
							out.write(barray[i]);
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
					bb.clear();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}

			String content = new String(out.toByteArray(), "UTF-8");
			resp.setContentType("text/xml");
			resp.setCharacterEncoding("UTF-8");
			try {
				resp.getWriter().write(content);
			} catch (Exception e) {
				resp.setStatus(500);
			}
		} else if (key != null && key.equals(Config.exchangeRatesKey)) {
			AppEngineFile f = fileService.getBlobFile(exchangeRates);
			FileReadChannel ch = null;
			try {
				ch = fileService.openReadChannel(f, false);
			} catch (Exception e) {
				e.printStackTrace();
			}

			ByteArrayOutputStream out = new ByteArrayOutputStream();
			long checkSum = 0L;
			try {
				byte[] barray = new byte[1024];
				ByteBuffer bb = ByteBuffer.wrap(barray);
				int nRead;
				while ((nRead = ch.read(bb)) != -1) {
					for (int i = 0; i < nRead; i++) {
						checkSum += barray[i];
						try {
							out.write(barray[i]);
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
					bb.clear();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}

			String content = new String(out.toByteArray(), "UTF-8");
			resp.setContentType("text/xml");
			resp.setCharacterEncoding("UTF-8");
			try {
				resp.getWriter().write(content);
			} catch (Exception e) {
				resp.setStatus(500);
			}
		} else if (key != null && key.equals(Config.mainKey)) {
			// Source source = CACHE.get(Config.mainKey);
			// if (source == null) {
			// resp.setStatus(204);
			// return;
			// }

			AppEngineFile f = fileService.getBlobFile(meteoKey);
			FileReadChannel ch = null;
			try {
				ch = fileService.openReadChannel(f, false);
			} catch (Exception e) {
				e.printStackTrace();
			}

			ByteArrayOutputStream out = new ByteArrayOutputStream();
			long checkSum = 0L;
			try {
				byte[] barray = new byte[1024];
				ByteBuffer bb = ByteBuffer.wrap(barray);
				int nRead;
				while ((nRead = ch.read(bb)) != -1) {
					for (int i = 0; i < nRead; i++) {
						checkSum += barray[i];
						try {
							out.write(barray[i]);
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
					bb.clear();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}

			String content = new String(out.toByteArray(), "UTF-8");
			resp.setContentType("text/xml");
			resp.setCharacterEncoding("UTF-8");
			try {
				resp.getWriter().write(content);
			} catch (Exception e) {
				resp.setStatus(500);
			}

			/*
			 * String filename = "/gs/" + Config.BUCKETNAME + "/" +
			 * Config.FILENAME; AppEngineFile readableFile = new
			 * AppEngineFile(filename); FileReadChannel readChannel =
			 * fileService.openReadChannel(readableFile, false);
			 * ByteArrayOutputStream out = new ByteArrayOutputStream(); long
			 * checkSum = 0L; try {
			 * 
			 * byte[] barray = new byte[1024]; ByteBuffer bb =
			 * ByteBuffer.wrap(barray); int nRead; while ((nRead =
			 * readChannel.read(bb)) != -1) {
			 * 
			 * for (int i = 0; i < nRead; i++) { checkSum += barray[i]; try {
			 * out.write(barray[i]); } catch (Exception e) {
			 * e.printStackTrace(); } } bb.clear(); } } catch (IOException e) {
			 * e.printStackTrace(); }
			 * 
			 * String content = new String(out.toByteArray(), "UTF-8");
			 * resp.setContentType("text/xml");
			 * resp.setCharacterEncoding("UTF-8"); try {
			 * resp.getWriter().write(content); } catch (Exception e) {
			 * resp.setStatus(500); }
			 */
		}else if (key != null && key.equals(Config.cleanBlobstore)){
			RefreshCache.cleanBlobstore();
			resp.setStatus(204);
			return;
		}
		if (city != null) {
			Source source = CACHE.get(city.toLowerCase());
			if (source == null) {
				resp.setStatus(204);
				return;
			}
			resp.setContentType("text/xml");
			try {
				XMLUtil.serialize(source, resp.getOutputStream(), OUTPUT_PROPERTIES);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				resp.setStatus(500);
			}
		}

	}
}
